package com.tabnet.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

import com.tabnet.beans.produit.Option;
import com.tabnet.beans.produit.ProduitCMD;
import com.tabnet.dao.DAOOptionCMD;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOFactory;
import com.tabnet.dao.DAOUtilitaire;

public class OptionCMDDAOImpl implements DAOOptionCMD{
	
	private static final String SQL_SELECT  		= "SELECT Ref_OPTCMD, Description_OPTCMD, PxOCMD, Choix "
			+ "FROM OptionsCMD o, CMD_OPT c WHERE o.Ref_OPTCMD = c.OPTC_Ref AND c.PRDC_ID = ?";
	private static final String SQL_LIER_CMD		= "INSERT INTO CMD_OPT VALUES (?, ?, ?)";
	private static final String SQL_DEL_OPT			= "DELETE FROM CMD_OPT WHERE PRDC_ID=? AND OPTC_Ref=?";
	private static final String SQL_DEL				= "DELETE FROM CMD_OPT WHERE PRDC_ID=?";
	
	private static final String SQL_INSERT			= "INSERT INTO OptionsCMD VALUES (?, ?, ?)";
	private static final String SQL_SELECT_LAST		= "SELECT Ref_OPTCMD FROM OptionsCMD WHERE Ref_OPTCMD LIKE ? "
			+ "ORDER BY Ref_OPTCMD DESC LIMIT 0 , 1";

	private DAOFactory _DaoFactory;
	
    public OptionCMDDAOImpl( DAOFactory pDaoFactory ) {
        this._DaoFactory = pDaoFactory;
    }
    
    /**
     * <p>Fonction map<br />
     * Simple méthode utilitaire permettant de faire la correspondance (le
     * mapping) entre une ligne issue de la table des options commander (un ResultSet) et
     * un bean Option.</p>
     * @param resultSet : objet ResultSet
     * @throws SQLException
     * @return un objet Option
     * */
    private Option map( ResultSet resultSet ) throws SQLException {
    	Option oOption = new Option();
    	
    	oOption.setRef( resultSet.getString( "Ref_OPTCMD" ) );
    	//Récupération que des options choisi par le client

    	oOption.setPxO(resultSet.getDouble( "PxOCMD" ));
    	oOption.setChoix(resultSet.getInt( "Choix" ));
    	
		String[] tabOption = resultSet.getString( "Description_OPTCMD" ).split("\\|");
    	oOption.setDescription(tabOption[oOption.getChoix()]);
    
        return oOption;
    }
    
    /**
     * <p>Fonction getLastRef<br />
     * Retourne la dernière référence d'une option</p>
     * @param pRef : reference d'une option
     * @throws SQLException
     * @return la derniere reference de la base
     * */
    private String getLastRef(String pRef) throws SQLException, DAOException {
		Connection oConnection = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        
        String strRef = "";

        try {
        	oConnection = this._DaoFactory.getConnection();
        	
            // récupération des accessoires commandes
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnection, SQL_SELECT_LAST, false, pRef + "%");
            resultSet = oPreparedStatement.executeQuery();
            
            if ( resultSet.next() )
            	strRef = resultSet.getString("Ref_OPTCMD");
        }
        catch ( SQLException e ) {
            throw new DAOException(e);
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnection );
        }

        return strRef;
    }
    
	@Override
	public Map<String, Option> getOptions(int pIdProduitCMD) throws DAOException {
		Connection oConnection = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        Map<String, Option> mapOptions = new HashMap<String, Option>();
        Option oOption;

        try {
        	oConnection = this._DaoFactory.getConnection();
        	
            // récupération des accessoires commandes
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnection, SQL_SELECT, false, pIdProduitCMD);
            resultSet = oPreparedStatement.executeQuery();
            while ( resultSet.next() ) {
            	oOption = map( resultSet );
            	mapOptions.put(oOption.getRef(), oOption);
            }
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnection );
        }

        return mapOptions;
	}
	
	@Override
	public void addOption(Option pOption) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	//Récuperation de la dernière reference de l'option
        	String strLastRef = this.getLastRef(pOption.getRef());
        	
        	if(strLastRef.length() == 8){
        		//Incrementation de cette derniere reference
        		int num = Integer.parseInt(strLastRef.substring(5)) + 1; 
        		String strNewRef = pOption.getRef();
        		
        		if(num < 10)
        			strNewRef += "00" + num; 
        		else if(num < 100)
        			strNewRef += "0" + num;
        		else
        			strNewRef += num;
	        	
				//insertion dans la table OptionCMD
				oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_INSERT, true, 
						strNewRef, pOption.getDescription(), pOption.getPxO());
		
	            if ( oPreparedStatement.executeUpdate() == 0 )
	                throw new DAOException( "Échec de l'insertion d'une option commander." );
        	}
        	else
                throw new DAOException( "Échec de la récupération de la dernière référence." );
	                
        }
        catch (SQLException e) {
            throw new DAOException(e);
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses(valeursAutoGenerees, oPreparedStatement, oConnexion);
        }
	}
	
	@SuppressWarnings("resource")
	@Override
	public void addOptions(ProduitCMD oProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	if(!oProduitCMD.getOptionsCmd().isEmpty()) {
	    		for(Option oOption : oProduitCMD.getOptionsCmd().values()){
	    			//insertion
	    			oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_LIER_CMD,
	    					true, oProduitCMD.getId(), this.getLastRef(oOption.getRef()), oOption.getChoix());
	
	                if ( oPreparedStatement.executeUpdate() == 0 )
	                    throw new DAOException( "Échec de la liaison d'un produit commander avec une option." );
	                
	                oPreparedStatement.close();
	    		}
        	}
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}

	@Override
	public void delOption(String pRefOption, int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion,
	    					SQL_DEL_OPT, true, pIdProduitCMD, pRefOption);
	
	        oPreparedStatement.executeUpdate();
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}

	@Override
	public void delOptions(int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion,
	    					SQL_DEL, true, pIdProduitCMD);
	
	        oPreparedStatement.executeUpdate();
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
		
	}

}
